﻿using System;
using System.Diagnostics;
using Mbs.Collections;
using Mbs.ComponentModel.Container.Activation;
using Mbs.ComponentModel.Container.Context;
using Mbs.ComponentModel.Container.Lifestyle;
using Mbs.ComponentModel.Container.Metadata;

namespace Mbs.ComponentModel.Container.Fluent
{
    [Serializable]
    class ComponentExpression : IBindingExpression, INamedExpression, IServiceExpression, IImplementationExpression, IFactoryExpression, IComponentInfo
    {
        public string Id { get; internal set; }
        public Type Service { get; internal set; }
        public Type Implementation { get; private set; }

        public bool IsLazyInit { get; set; }
        public string Activator { get; set; }
        public string Lifestyle { get; set; }
        public IPropertySet ExtendedProperties { get; private set; }

        public Func<ICreateContext, object> Factory { get; private set; }

        public IServiceRegistry Registry { get; set; }

        public ComponentExpression()
        {
            IsLazyInit = true;
            Activator = ActivatorType.Default;
            Lifestyle = LifestyleType.Singleton;
            ExtendedProperties = new PropertySet(StringComparer.OrdinalIgnoreCase);
        }



        public INamedExpression Named(string id)
        {
            if (string.IsNullOrEmpty(id))
                throw new ArgumentNullException("id == null");
            Id = id;

            return this;
        }


        #region INamedExpression Members

        public IServiceExpression Bind(Type serive)
        {
            Service = serive;
            return this;
        }

        public IServiceExpression Bind<TService>()
        {
            Service = typeof(TService);
            return this;
        }


        public IServiceExpression Bind(Type serive,string id)
        {
            Service = serive;
            return Named(id);
        }

        public IServiceExpression Bind<TService>(string id)
        {
            Service = typeof(TService);
            return Named(id);
        }

        #endregion

        #region IServiceExpression Members

        public IImplementationExpression To(Type type)
        {
            Implementation = type;
            Trace.Assert(type != null, "implemention == null");
            return this;
        }

        public IImplementationExpression To<TImplementation>()
        {
            Implementation = typeof(TImplementation);
            return this;
        }

        IFactoryExpression IServiceExpression.Factory(Func<ICreateContext, object> factory)
        {
            Trace.Assert(factory != null, "factory == null");
            Factory = factory;
            Activator = ActivatorType.Factory;
            return this;
        }

        #endregion

        #region IImplementationExpression Members

        public IImplementationExpression Eager()
        {
            IsLazyInit = false;
            return this;
        }

        IImplementationExpression IImplementationExpression.Lifestyle(string lifestyle)
        {
            Lifestyle = lifestyle;
            return this;
        }

        IImplementationExpression IImplementationExpression.Activator(string activator)
        {
            Activator = activator;
            return this;
        }

        public IImplementationExpression Add(string key, object value)
        {
            ExtendedProperties.Set(key, value);
            return this;
        }

        #endregion

        public override bool Equals(object obj)
        {
            return Equals((IComponentInfo)obj);
        }

        public bool Equals(IComponentInfo other)
        {
            if (other == null)
                return false;
            if (Implementation != other.Implementation)
                return false;
            if (Service != other.Service)
                return false;
            return true;
        }

        public override int GetHashCode()
        {
            return Id.GetHashCode();
        }

        #region IFactoryExpression Members

        IFactoryExpression IFactoryExpression.Eager()
        {
            IsLazyInit = false;
            return this;
        }

        IFactoryExpression IFactoryExpression.Lifestyle(string lifestyle)
        {
            Lifestyle = lifestyle;
            return this;
        }



        IFactoryExpression IFactoryExpression.Add(string key, object value)
        {
            ExtendedProperties.Set(key, value);
            return this;
        }

        #endregion
    }

}
